home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gdevps.c < prev    next >
C/C++ Source or Header  |  1997-06-20  |  23KB  |  799 lines

  1. /* Copyright (C) 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gdevps.c */
  20. /* PostScript-writing driver */
  21. #include "math_.h"
  22. #include "time_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gscdefs.h"
  26. #include "gsmatrix.h"        /* for gsiparam.h */
  27. #include "gsiparam.h"
  28. #include "gsparam.h"
  29. #include "gxdevice.h"
  30. #include "gscspace.h"
  31. #include "gxdcolor.h"
  32. #include "gdevpsdf.h"
  33. #include "gdevpstr.h"
  34. #include "strimpl.h"
  35. #include "sa85x.h"
  36.  
  37. /****************************************************************
  38.  * Notes:
  39.  *    ASCII85EncodePages should use ASCIIHexEncode if LanguageLevel < 2.
  40.  *    Images are never compressed; in fact, none of the other
  41.  *      Distiller parameters do anything.
  42.  ****************************************************************/
  43.  
  44. /* ---------------- Device definition ---------------- */
  45.  
  46. /* Define the size of the internal stream buffer. */
  47. /* (This is not a limitation: it only affects performance.) */
  48. #define sbuf_size 512
  49.  
  50. /* Device procedures */
  51. private dev_proc_open_device(psw_open);
  52. private dev_proc_output_page(psw_output_page);
  53. private dev_proc_close_device(psw_close);
  54. private dev_proc_copy_mono(psw_copy_mono);
  55. private dev_proc_copy_color(psw_copy_color);
  56. private dev_proc_put_params(psw_put_params);
  57. private dev_proc_get_params(psw_get_params);
  58. private dev_proc_fill_mask(psw_fill_mask);
  59. private dev_proc_begin_image(psw_begin_image);
  60. private dev_proc_image_data(psw_image_data);
  61. private dev_proc_end_image(psw_end_image);
  62.  
  63. #define X_DPI 720
  64. #define Y_DPI 720
  65.  
  66. typedef struct gx_device_pswrite_s {
  67.   gx_device_psdf_common;
  68.     /* Settable parameters */
  69. #define LanguageLevel_default 2.0
  70.   float LanguageLevel;
  71.     /* End of parameters */
  72.   bool ProduceEPS;
  73.   bool first_page;
  74.   long bbox_position;
  75.   stream *image_stream;
  76.   byte *image_buf;
  77. #define num_cached_images 137
  78.   gx_bitmap_id image_cache[num_cached_images];
  79. } gx_device_pswrite;
  80.  
  81. gs_private_st_suffix_add2_final(st_device_pswrite, gx_device_pswrite,
  82.   "gx_device_pswrite", device_pswrite_enum_ptrs, device_pswrite_reloc_ptrs,
  83.   gx_device_finalize, st_device_vector, image_stream, image_buf);
  84.  
  85. #define psw_procs\
  86.     {    psw_open,\
  87.         gx_upright_get_initial_matrix,\
  88.         NULL,            /* sync_output */\
  89.         psw_output_page,\
  90.         psw_close,\
  91.         gx_default_rgb_map_rgb_color,\
  92.         gx_default_rgb_map_color_rgb,\
  93.         gdev_vector_fill_rectangle,\
  94.         NULL,            /* tile_rectangle */\
  95.         psw_copy_mono,\
  96.         psw_copy_color,\
  97.         NULL,            /* draw_line */\
  98.         NULL,            /* get_bits */\
  99.         psw_get_params,\
  100.         psw_put_params,\
  101.         NULL,            /* map_cmyk_color */\
  102.         NULL,            /* get_xfont_procs */\
  103.         NULL,            /* get_xfont_device */\
  104.         NULL,            /* map_rgb_alpha_color */\
  105.         gx_page_device_get_page_device,\
  106.         NULL,            /* get_alpha_bits */\
  107.         NULL,            /* copy_alpha */\
  108.         NULL,            /* get_band */\
  109.         NULL,            /* copy_rop */\
  110.         gdev_vector_fill_path,\
  111.         gdev_vector_stroke_path,\
  112.         psw_fill_mask,\
  113.         gdev_vector_fill_trapezoid,\
  114.         gdev_vector_fill_parallelogram,\
  115.         gdev_vector_fill_triangle,\
  116.         NULL /****** WRONG ******/,    /* draw_thin_line */\
  117.         psw_begin_image,\
  118.         psw_image_data,\
  119.         psw_end_image,\
  120.         NULL,            /* strip_tile_rectangle */\
  121.         NULL/******psw_strip_copy_rop******/\
  122.     }
  123.  
  124. gx_device_pswrite far_data gs_pswrite_device =
  125. {    std_device_dci_type_body(gx_device_pswrite, 0, "pswrite",
  126.       &st_device_pswrite,
  127.       DEFAULT_WIDTH_10THS*X_DPI/10, DEFAULT_HEIGHT_10THS*Y_DPI/10,
  128.       X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256),
  129.     psw_procs,
  130.     psdf_initial_values(1 /*true*/),    /* (ASCII85EncodePages) */
  131.     LanguageLevel_default,    /* LanguageLevel */
  132.     0/*false*/        /* ProduceEPS */
  133. };
  134.  
  135. gx_device_pswrite far_data gs_epswrite_device =
  136. {    std_device_dci_type_body(gx_device_pswrite, 0, "epswrite",
  137.       &st_device_pswrite,
  138.       DEFAULT_WIDTH_10THS*X_DPI/10, DEFAULT_HEIGHT_10THS*Y_DPI/10,
  139.       X_DPI, Y_DPI, 3, 24, 255, 255, 256, 256),
  140.     psw_procs,
  141.     psdf_initial_values(1 /*true*/),    /* (ASCII85EncodePages) */
  142.     LanguageLevel_default,    /* LanguageLevel */
  143.     1/*true*/        /* ProduceEPS */
  144. };
  145.  
  146. /* Vector device implementation */
  147. private int psw_beginpage(P1(gx_device_vector *vdev));
  148. private int psw_setcolors(P2(gx_device_vector *vdev,
  149.                  const gx_drawing_color *pdc));
  150. private int psw_endpath(P2(gx_device_vector *vdev, gx_path_type_t type));
  151. private const gx_device_vector_procs psw_vector_procs = {
  152.     /* Page management */
  153.   psw_beginpage,
  154.     /* Imager state */
  155.   psdf_setlinewidth,
  156.   psdf_setlinecap,
  157.   psdf_setlinejoin,
  158.   psdf_setmiterlimit,
  159.   psdf_setdash,
  160.   psdf_setflat,
  161.   psdf_setlogop,
  162.     /* Other state */
  163.   psw_setcolors,        /* fill & stroke colors are the same */
  164.   psw_setcolors,
  165.     /* Paths */
  166.   psdf_dopath,
  167.   psdf_dorect,
  168.   psdf_beginpath,
  169.   psdf_moveto,
  170.   psdf_lineto,
  171.   psdf_curveto,
  172.   psdf_closepath,
  173.   psw_endpath
  174. };
  175.  
  176. /* ---------------- File header ---------------- */
  177.  
  178. private const char *psw_ps_header[] = {
  179. "%!PS-Adobe-3.0",
  180. "%%Pages: (atend)",
  181. 0
  182. };
  183.  
  184. private const char *psw_eps_header[] = {
  185. "%!PS-Adobe-3.0 EPSF-3.0",
  186. 0
  187. };
  188.  
  189. private const char *psw_header[] = {
  190. "%%EndComments",
  191. "%%BeginProlog",
  192. "% This copyright applies to everything between here and the %%EndProlog:",
  193. 0
  194. };
  195.  
  196. private const char *psw_prolog[] = {
  197. "%%BeginResource: procset GS_pswrite_ProcSet",
  198. "/GS_pswrite_ProcSet 40 dict dup begin",
  199. "/!{bind def}bind def/X{load def}!",
  200. "/rg/setrgbcolor X/g/setgray X/w/setlinewidth X/J/setlinecap X",
  201. "/j/setlinejoin X/M/setmiterlimit X/d/setdash X/i/setflat X",
  202. "/m/moveto X/l/lineto X/c/curveto X/h/closepath X",
  203. "/lx{0 rlineto}!/ly{0 exch rlineto}!/v{currentpoint 6 2 roll c}!/y{2 copy c}!",
  204. "/re{4 -2 roll m exch dup lx exch ly neg lx h}!",
  205. "/q/gsave X/Q/grestore X/f/fill X/f*/eofill X/S/stroke X/rf{re f}!",
  206. "/Y{initclip clip newpath}!/Y*{initclip eoclip newpath}!/rY{re Y}!",
  207. "/@/currentfile X/|{string readstring pop}!",
  208.     /* <w> <h> <x> <y> <bps/inv> <src> Ix <w> <h> <bps/inv> <mtx> <src> */
  209. "/Ix{[1 0 0 1 9 -1 roll neg 9 -1 roll neg]exch}!",
  210. "/It{true exch Ix imagemask}!/If{false exch Ix imagemask}!/I{exch Ix image}!",
  211. 0
  212. };
  213.  
  214. private const char *psw_1_prolog[] = {
  215. 0
  216. };
  217.  
  218. private const char *psw_1_5_prolog[] = {
  219. "/Ic{Ix false 1 colorimage}!",
  220. 0
  221. };
  222.  
  223. private const char *psw_2_prolog[] = {
  224. "/@85{@/ASCII85Decode filter}!",
  225. 0
  226. };
  227.  
  228. private const char *psw_end_prolog[] = {
  229. "end def",
  230. "%%EndResource",
  231. "%%EndProlog",
  232. 0
  233. };
  234.  
  235. private void
  236. psw_put_lines(stream *s, const char **lines)
  237. {    int i;
  238.     for ( i = 0; lines[i] != 0; ++i )
  239.       pprints1(s, "%s\n", lines[i]);
  240. }
  241.  
  242. /* ---------------- Utilities ---------------- */
  243.  
  244. /* Reset the image cache. */
  245. private void
  246. image_cache_reset(gx_device_pswrite *pdev)
  247. {    int i;
  248.     for ( i = 0; i < num_cached_images; ++i )
  249.       pdev->image_cache[i] = gx_no_bitmap_id;
  250. }
  251.  
  252. /* Look up or enter an image ID in the cache. */
  253. /* If id is gx_no_bitmap_id or enter is false, do not enter it. */
  254. private bool
  255. image_cache_lookup(gx_device_pswrite *pdev, gx_bitmap_id id, bool enter)
  256. {    int i;
  257.  
  258.     if ( id == gx_no_bitmap_id )
  259.       return false;
  260.     i = id % num_cached_images;
  261.     if ( pdev->image_cache[i] == id )
  262.       return true;
  263.     if ( enter )
  264.       pdev->image_cache[i] = id;
  265.     return false;
  266. }
  267.  
  268. /* Set up to write a device-pixel image. */
  269. /* Return false if the image is empty. */
  270. private bool
  271. psw_image_setup(gx_device_pswrite *pdev, int x, int y, int w, int h)
  272. {    stream *s = pdev->strm;
  273.  
  274.     if ( w <= 0 || h <= 0 )
  275.       return false;
  276.     pprintd4(s, "%d %d %d %d ", w, h, x, y);
  277.     return true;
  278. }
  279.  
  280. /* Prepare the encoding stream for image data. */
  281. /* Return 1 if we are using ASCII85 encoding. */
  282. private const stream_procs filter_write_procs =
  283. {    s_std_noavailable, s_std_noseek, s_std_write_reset,
  284.     s_std_write_flush, s_filter_close
  285. };
  286. private int
  287. psw_image_stream_setup(gx_device_pswrite *pdev)
  288. {    pdev->image_stream = gdev_vector_stream((gx_device_vector *)pdev);
  289.     if ( pdev->LanguageLevel >= 2 && pdev->params.ASCII85EncodePages )
  290.       { gs_memory_t *mem = pdev->v_memory;
  291.         stream *prev_stream = pdev->image_stream;
  292.         uint buf_size = 200; /* arbitrary */
  293.         byte *buf = pdev->image_buf =
  294.           gs_alloc_bytes(mem, buf_size, "psw_set_image_stream(buf)");
  295.         stream *es = pdev->image_stream =
  296.           s_alloc(mem, "psw_set_image_stream(stream)");
  297.  
  298.         if ( es == 0 || buf == 0 )
  299.           { return_error(gs_error_VMerror);
  300.           }
  301.         s_std_init(es, buf, buf_size, &filter_write_procs, s_mode_write);
  302.         es->template = &s_A85E_template;
  303.         es->procs.process = es->template->process;
  304.         es->strm = prev_stream;
  305.         return 1;
  306.       }
  307.     return 0;
  308. }
  309.  
  310. /* Clean up after writing an image. */
  311. private void
  312. psw_image_cleanup(gx_device_pswrite *pdev)
  313. {    gs_memory_t *mem = pdev->v_memory;
  314.  
  315.     if ( pdev->image_stream != 0 && pdev->image_stream != pdev->strm )
  316.       { sclose(pdev->image_stream);
  317.         gs_free_object(mem, pdev->image_stream, "psw_image_cleanup(stream)");
  318.         pdev->image_stream = 0;
  319.       }
  320.     if ( pdev->image_buf )
  321.       { gs_free_object(mem, pdev->image_buf, "psw_image_cleanup(buf)");
  322.         pdev->image_buf = 0;
  323.       }
  324. }
  325.  
  326. /* Write data for an image. */
  327. /****** IGNORES data_x ******/
  328. private void
  329. psw_put_bits(stream *s, const byte *data, int data_x_bit, uint raster,
  330.   uint width_bits, int height)
  331. {    int y;
  332.     for ( y = 0; y < height; ++y )
  333.       pwrite(s, data + (data_x_bit >> 3) + y * raster,
  334.          (width_bits + 7) >> 3);
  335. }
  336. private int
  337. psw_image_write(gx_device_pswrite *pdev, const char *imagestr,
  338.   const byte *data, int data_x_bit, uint raster, gx_bitmap_id id,
  339.   uint width_bits, int height)
  340. {    stream *s = pdev->strm;
  341.     int code;
  342.     const char *source;
  343.  
  344.     if ( image_cache_lookup(pdev, id, false) )
  345.       { pprintld1(s, "I%ld ", id);
  346.         pprints1(s, "%s\n", imagestr);
  347.         return 0;
  348.       }
  349.     code = psw_image_stream_setup(pdev);
  350.     if ( code < 0 )
  351.       return code;
  352.     source = (code ? "@85" : "@");
  353.     if ( id == gx_no_bitmap_id || width_bits * (ulong)height > 8000 ||
  354.          width_bits == 0 || height == 0
  355.        )
  356.       { pprints2(s, "%s %s\n", source, imagestr);
  357.         psw_put_bits(pdev->image_stream, data, data_x_bit, raster,
  358.              width_bits, height);
  359.         psw_image_cleanup(pdev);
  360.         spputc(s, '\n');
  361.       }
  362.     else
  363.       { char str[40];
  364.  
  365.         image_cache_lookup(pdev, id, true);
  366.         sprintf(str, "/I%ld %s %ld |\n",
  367.             id, source, ((width_bits + 7) >> 3) * (ulong)height);
  368.         pputs(s, str);
  369.         psw_put_bits(pdev->image_stream, data, data_x_bit, raster,
  370.              width_bits, height);
  371.         psw_image_cleanup(pdev);
  372.         pprintld1(s, "\ndef I%ld ", id);
  373.         pprints1(s, "%s\n", imagestr);
  374.       }
  375.     return 0;
  376. }
  377.  
  378. /* Print a matrix. */
  379. private void
  380. psw_put_matrix(stream *s, const gs_matrix *pmat)
  381. {    pprintg6(s, "[%g %g %g %g %g %g]",
  382.          pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
  383. }
  384.  
  385. /* ---------------- Vector device implementation ---------------- */
  386.  
  387. #define pdev ((gx_device_pswrite *)vdev)
  388.  
  389. private int
  390. psw_beginpage(gx_device_vector *vdev)
  391. {    stream *s = vdev->strm;
  392.     long page = vdev->PageCount + 1;
  393.  
  394.     if ( pdev->first_page )
  395.       { psw_put_lines(s,
  396.               (pdev->ProduceEPS ? psw_eps_header : psw_ps_header));
  397.         if ( ftell(vdev->file) < 0 )
  398.           { /* File is not seekable. */
  399.         pdev->bbox_position = -1;
  400.         pputs(s, "%%BoundingBox: (atend)\n");
  401.           }
  402.         else
  403.           { /* File is seekable, leave room to rewrite bbox. */
  404.         pdev->bbox_position = stell(s);
  405.         pputs(s, "................................................................\n");
  406.           }
  407.         pprints1(s, "%%%%Creator: %s ", gs_product);
  408.         pprintld1(s, "%ld ", (long)gs_revision);
  409.         pprints1(s, "(%s)\n", vdev->dname);
  410.         { struct tm tms;
  411.           time_t t;
  412.           char date_str[25];
  413.  
  414.           time(&t);
  415.           tms = *localtime(&t);
  416.           sprintf(date_str, "%d/%02d/%02d %02d:%02d:%02d",
  417.               tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
  418.               tms.tm_hour, tms.tm_min, tms.tm_sec);
  419.           pprints1(s, "%%%%CreationDate: %s\n", date_str);
  420.         }
  421.         if ( pdev->params.ASCII85EncodePages )
  422.           pputs(s, "%%DocumentData: Clean7Bit\n");
  423.         if ( pdev->LanguageLevel == 2.0 )
  424.           pputs(s, "%%LanguageLevel: 2\n");
  425.         else if ( pdev->LanguageLevel == 1.5 )
  426.           pputs(s, "%%Extensions: CMYK\n");
  427.         psw_put_lines(s, psw_header);
  428.         pprints1(s, "%% %s\n", gs_copyright);
  429.         psw_put_lines(s, psw_prolog);
  430.         if ( pdev->LanguageLevel < 1.5 )
  431.           psw_put_lines(s, psw_1_prolog);
  432.         else
  433.           { psw_put_lines(s, psw_1_5_prolog);
  434.             if ( pdev->LanguageLevel > 1.5 )
  435.           psw_put_lines(s, psw_2_prolog);
  436.           }
  437.         psw_put_lines(s, psw_end_prolog);
  438.       }
  439.     pprintld2(s, "%%%%Page: %ld %ld\n%%%%BeginPageSetup\n", page, page);
  440.     pprintg2(s, "save GS_pswrite_ProcSet begin %g %g scale\n%%%%EndPageSetup\n",
  441.          72.0 / vdev->HWResolution[0], 72.0 / vdev->HWResolution[1]);
  442.     return 0;
  443. }
  444.  
  445. private int
  446. psw_setcolors(gx_device_vector *vdev, const gx_drawing_color *pdc)
  447. {    /* PostScript only keeps track of a single color. */
  448.     vdev->fill_color = *pdc;
  449.     vdev->stroke_color = *pdc;
  450.     return psdf_setfillcolor(vdev, pdc);
  451. }
  452.  
  453. private int
  454. psw_endpath(gx_device_vector *vdev, gx_path_type_t type)
  455. {    stream *s = vdev->strm;
  456.     const char *star = (type & gx_path_type_even_odd ? "*" : "");
  457.  
  458.     if ( type & gx_path_type_fill )
  459.       { if ( type & (gx_path_type_stroke | gx_path_type_clip) )
  460.           pprints1(s, "q f%s Q ", star);
  461.         else
  462.           pprints1(s, "f%s\n", star);
  463.       }
  464.     if ( type & gx_path_type_stroke )
  465.       { if ( type & gx_path_type_clip )
  466.           pputs(s, "q S Q ");
  467.         else
  468.           pputs(s, "S\n");
  469.       }
  470.     if ( type & gx_path_type_clip )
  471.       pprints1(s, "Y%s\n", star);
  472.     return 0;
  473. }
  474.  
  475. #undef pdev
  476.  
  477. /* ---------------- Driver procedures ---------------- */
  478.  
  479. #define vdev ((gx_device_vector *)dev)
  480. #define pdev ((gx_device_pswrite *)dev)
  481.  
  482. /* ------ Open/close/page ------ */
  483.  
  484. /* Open the device. */
  485. private int
  486. psw_open(gx_device *dev)
  487. {    vdev->v_memory = dev->memory; /****** WRONG ******/
  488.     vdev->vec_procs = &psw_vector_procs;
  489.     { int code = gdev_vector_open_file_bbox(vdev, 512, true);
  490.       if ( code < 0 )
  491.         return code;
  492.     }
  493.     gdev_vector_init(vdev);
  494.     pdev->first_page = true;
  495.     image_cache_reset(pdev);
  496.     return 0;
  497. }
  498.  
  499. /* Wrap up ("output") a page. */
  500. private int
  501. psw_output_page(gx_device *dev, int num_copies, int flush)
  502. {    stream *s = gdev_vector_stream(vdev);
  503.     if ( num_copies != 1 )
  504.       pprintd1(s, "userdict /#copies %d put\n", num_copies);
  505.     pprints1(s, "end %s restore\n%%%%PageTrailer\n",
  506.          (flush ? "showpage" : "copypage"));
  507.     sflush(s);
  508.     vdev->in_page = false;
  509.     pdev->first_page = false;
  510.     gdev_vector_reset(vdev);
  511.     image_cache_reset(pdev);
  512.     return 0;
  513. }
  514.  
  515. /* Close the device. */
  516. /* Note that if this is being called as a result of finalization, */
  517. /* the stream may no longer exist; but the file will still be open. */
  518. private int
  519. psw_close(gx_device *dev)
  520. {    FILE *f = vdev->file;
  521.  
  522.     fprintf(f, "%%%%Trailer\n%%%%Pages: %ld\n", dev->PageCount);
  523.     { gs_rect bbox;
  524.       long save_pos;
  525.  
  526.       gx_device_bbox_bbox(vdev->bbox_device, &bbox);
  527.       if ( pdev->bbox_position >= 0 )
  528.         { save_pos = ftell(f);
  529.           fseek(f, pdev->bbox_position, SEEK_SET);
  530.         }
  531.       fprintf(f, "%%%%BoundingBox: %d %d %d %d\n",
  532.           (int)floor(bbox.p.x), (int)floor(bbox.p.y),
  533.           (int)ceil(bbox.q.x), (int)ceil(bbox.q.y));
  534.       if ( pdev->bbox_position >= 0 )
  535.         { fputc('%', f);
  536.           fseek(f, save_pos, SEEK_SET);
  537.         }
  538.     }
  539.     if ( !pdev->ProduceEPS )
  540.       fputs("%%EOF\n", f);
  541.     gdev_vector_close_file(vdev);
  542.     return 0;
  543. }
  544.  
  545. /* ---------------- Get/put parameters ---------------- */
  546.  
  547. /* Get parameters. */
  548. private int
  549. psw_get_params(gx_device *dev, gs_param_list *plist)
  550. {    int code = gdev_psdf_get_params(dev, plist);
  551.     int ecode;
  552.  
  553.     if ( code < 0 )
  554.       return code;
  555.     if ( (ecode = param_write_float(plist, "LanguageLevel", &pdev->LanguageLevel)) < 0 )
  556.       return ecode;
  557.     return code;
  558. }
  559.  
  560. /* Put parameters. */
  561. private int
  562. psw_put_params(gx_device *dev, gs_param_list *plist)
  563. {    int ecode = 0;
  564.     int code;
  565.     gs_param_name param_name;
  566.     float ll = pdev->LanguageLevel;
  567.  
  568.     switch ( code = param_read_float(plist, (param_name = "LanguageLevel"), &ll) )
  569.       {
  570.       case 0:
  571.         if ( ll == 1.0 || ll == 1.5 || ll == 2.0 )
  572.           break;
  573.         code = gs_error_rangecheck;
  574.       default:
  575.         ecode = code;
  576.         param_signal_error(plist, param_name, ecode);
  577.       case 1:
  578.         ;
  579.       }
  580.  
  581.     if ( ecode < 0 )
  582.       return ecode;
  583.     code = gdev_psdf_put_params(dev, plist);
  584.     if ( code < 0 )
  585.       return code;
  586.  
  587.     pdev->LanguageLevel = ll;
  588.     return code;
  589. }
  590.  
  591. /* ---------------- Images ---------------- */
  592.  
  593. /* Copy a monochrome bitmap. */
  594. private int
  595. psw_copy_mono(gx_device *dev, const byte *data,
  596.   int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h,
  597.   gx_color_index zero, gx_color_index one)
  598. {    gx_drawing_color color;
  599.     const char *op;
  600.     int code = 0;
  601.  
  602.     (*dev_proc(vdev->bbox_device, copy_mono))
  603.       ((gx_device *)vdev->bbox_device, data, data_x, raster, id,
  604.        x, y, w, h, zero, one);
  605.     if ( one == gx_no_color_index )
  606.       { color_set_pure(&color, zero);
  607.         code = gdev_vector_update_fill_color((gx_device_vector *)pdev,
  608.                          &color);
  609.         op = "If";
  610.       }
  611.     else if ( zero == vdev->black && one == vdev->white )
  612.       op = "1 I";
  613.     else
  614.       { if ( zero != gx_no_color_index )
  615.           { code = (*dev_proc(dev, fill_rectangle))(dev, x, y, w, h, zero);
  616.             if ( code < 0 )
  617.           return code;
  618.           }
  619.         color_set_pure(&color, one);
  620.         code = gdev_vector_update_fill_color((gx_device_vector *)pdev,
  621.                          &color);
  622.         op = "It";
  623.       }
  624.     if ( code < 0 )
  625.       return 0;
  626.     return (psw_image_setup(pdev, x, y, w, h) ?
  627.         psw_image_write(pdev, op, data, data_x, raster, id,
  628.                        w, h) : 0);
  629. }
  630.  
  631. /* Copy a color bitmap. */
  632. private int
  633. psw_copy_color(gx_device *dev,
  634.   const byte *data, int data_x, int raster, gx_bitmap_id id,
  635.   int x, int y, int w, int h)
  636. {    int depth = dev->color_info.depth;
  637.  
  638.     (*dev_proc(vdev->bbox_device, copy_color))
  639.       ((gx_device *)vdev->bbox_device, data, data_x, raster, id,
  640.        x, y, w, h);
  641.     if ( !psw_image_setup(pdev, x, y, w, h) )
  642.       return 0;
  643.     pprintd1(pdev->strm, " %d", depth);
  644.     return psw_image_write(pdev, "Ic", data, data_x * depth,
  645.                       raster, id, w * depth, h);
  646. }
  647.  
  648. /* Fill a mask. */
  649. private int
  650. psw_fill_mask(gx_device *dev,
  651.   const byte *data, int data_x, int raster, gx_bitmap_id id,
  652.   int x, int y, int w, int h,
  653.   const gx_drawing_color *pdcolor, int depth,
  654.   gs_logical_operation_t lop, const gx_clip_path *pcpath)
  655. {    if ( depth > 1 ||
  656.          gdev_vector_update_fill_color(vdev, pdcolor) < 0 ||
  657.          gdev_vector_update_clip_path(vdev, pcpath) < 0 ||
  658.          gdev_vector_update_log_op(vdev, lop) < 0
  659.        )
  660.       return gx_default_fill_mask(dev, data, data_x, raster, id,
  661.                       x, y, w, h, pdcolor, depth, lop, pcpath);
  662.     (*dev_proc(vdev->bbox_device, fill_mask))
  663.       ((gx_device *)vdev->bbox_device, data, data_x, raster, id,
  664.        x, y, w, h, pdcolor, depth, lop, pcpath);
  665.     return (psw_image_setup(pdev, x, y, w, h) ?
  666.         psw_image_write(pdev, "It",
  667.                        data, data_x, raster, id, w, h) : 0);
  668. }
  669.  
  670. /* ---------------- High-level images ---------------- */
  671.  
  672. /* Start processing an image. */
  673. private int
  674. psw_begin_image(gx_device *dev,
  675.   const gs_imager_state *pis, const gs_image_t *pim,
  676.   gs_image_format_t format, const gs_int_rect *prect,
  677.   const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,
  678.   gs_memory_t *mem, void **pinfo)
  679. {    gdev_vector_image_enum_t *pie =
  680.       gs_alloc_struct(mem, gdev_vector_image_enum_t,
  681.               &st_vector_image_enum, "psw_begin_image");
  682.     const gs_color_space *pcs = pim->ColorSpace;
  683.     gs_color_space_index index;
  684.     int num_components;
  685.     bool can_do = prect == 0;
  686.     int code;
  687.  
  688.     if ( pie == 0 )
  689.       return_error(gs_error_VMerror);
  690.     pie->memory = mem;
  691.     *pinfo = pie;
  692.     if ( !pim->ImageMask )
  693.       { index = gs_color_space_get_index(pcs);
  694.         num_components = gs_color_space_num_components(pcs);
  695.       }
  696.     if ( pdev->LanguageLevel < 2 && !pim->ImageMask )
  697.       { /*
  698.          * Restrict ourselves to Level 1 images: device color spaces, [0
  699.          * 1] decode, bits per component <= 8, no CombineWithColor.
  700.          */
  701.         if ( pim->BitsPerComponent > 8 || pim->CombineWithColor )
  702.           can_do = false;
  703.         else
  704.           { int i;
  705.  
  706.         switch ( index )
  707.           {
  708.           case gs_color_space_index_DeviceGray:
  709.           case gs_color_space_index_DeviceRGB:
  710.           case gs_color_space_index_DeviceCMYK:
  711.             for ( i = 0; i < num_components * 2; ++i )
  712.               if ( pim->Decode[i] != (i & 1) )
  713.             can_do = false;
  714.             break;
  715.           default:
  716.             can_do = false;
  717.           }
  718.           }
  719.       }
  720.     if ( !can_do ||
  721.          gdev_vector_begin_image(vdev, pis, pim, format, prect, pdcolor,
  722.                      pcpath, mem, pie) < 0 ||
  723.          (code = psw_image_stream_setup(pdev)) < 0
  724.        )
  725.       return gx_default_begin_image(dev, pis, pim, format, prect,
  726.                     pdcolor, pcpath, mem,
  727.                     &pie->default_info);
  728.     /* Write the image/colorimage/imagemask preamble. */
  729.     { stream *s = gdev_vector_stream((gx_device_vector *)pdev);
  730.       const char *source = (code ? "@85" : "@");
  731.       gs_matrix imat;
  732.  
  733.       pputs(s, "q");
  734.       (*dev_proc(dev, get_initial_matrix))(dev, &imat);
  735.       gs_matrix_scale(&imat, 72.0 / dev->HWResolution[0],
  736.               72.0 / dev->HWResolution[1], &imat);
  737.       gs_matrix_invert(&imat, &imat);
  738.       gs_matrix_multiply(&ctm_only(pis), &imat, &imat);
  739.       psw_put_matrix(s, &imat);
  740.       pprintd2(s, "concat\n%d %d ", pie->width, pie->height);
  741.       if ( pim->ImageMask )
  742.         { pputs(s, (pim->Decode[0] == 0 ? "false" : "true"));
  743.           psw_put_matrix(s, &pim->ImageMatrix);
  744.           pprints1(s, "%s imagemask\n", source);
  745.         }
  746.       else
  747.         { pprintd1(s, "%d", pim->BitsPerComponent);
  748.           psw_put_matrix(s, &pim->ImageMatrix);
  749.           if ( index == gs_color_space_index_DeviceGray )
  750.         pprints1(s, "%s image\n", source);
  751.           else
  752.         { if ( format == gs_image_format_chunky )
  753.             pprints1(s, "%s false", source);
  754.           else
  755.             pprints2(s, "%s %strue", source,
  756.                  "dup dup dup " + (16 - num_components * 4));
  757.           pprintd1(s, " %d colorimage\n", num_components);
  758.         }
  759.         }
  760.     }
  761.     return 0;
  762. }
  763.  
  764. /* Process the next piece of an image. */
  765. private int
  766. psw_image_data(gx_device *dev,
  767.   void *info, const byte **planes, int data_x, uint raster, int height)
  768. {    gdev_vector_image_enum_t *pie = info;
  769.  
  770.     if ( pie->default_info )
  771.       return gx_default_image_data(dev, pie->default_info, planes,
  772.                        data_x, raster, height);
  773.     (*dev_proc(vdev->bbox_device, image_data))
  774.       ((gx_device *)vdev->bbox_device, pie->bbox_info,
  775.        planes, data_x, raster, height);
  776.     { int plane;
  777.       for ( plane = 0; plane < pie->num_planes; ++plane )
  778.         psw_put_bits(pdev->image_stream, planes[plane],
  779.              data_x * pie->bits_per_pixel, raster,
  780.              pie->bits_per_row, height);
  781.     }
  782.     return (pie->y += height) >= pie->height;
  783. }
  784.  
  785. /* Clean up by releasing the buffers. */
  786. private int
  787. psw_end_image(gx_device *dev, void *info, bool draw_last)
  788. {    gdev_vector_image_enum_t *pie = info;
  789.     int code;
  790.  
  791.     code = gdev_vector_end_image(vdev, (gdev_vector_image_enum_t *)pie,
  792.                      draw_last, pdev->white);
  793.     if ( code > 0 )
  794.       { psw_image_cleanup(pdev);
  795.         pputs(pdev->strm, "\nQ\n");
  796.       }
  797.     return code;
  798. }
  799.